package scatter.wwd.rest.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import scatter.area.pojo.po.Area;
import scatter.area.rest.service.IAreaService;
import scatter.comment.pojo.enjoy.po.CommentEnjoy;
import scatter.comment.pojo.star.po.CommentStar;
import scatter.comment.rest.enjoy.mapstruct.CommentEnjoyMapStruct;
import scatter.comment.rest.enjoy.service.ICommentEnjoyService;
import scatter.comment.rest.rate.service.ICommentRateService;
import scatter.comment.rest.star.mapstruct.CommentStarMapStruct;
import scatter.comment.rest.star.service.ICommentStarService;
import scatter.common.pojo.form.BasePageQueryForm;
import scatter.common.rest.exception.BusinessDataNotFoundException;
import scatter.common.rest.exception.BusinessException;
import scatter.common.rest.exception.UserNotLoginException;
import scatter.common.rest.service.IBaseAddUpdateQueryFormServiceImpl;
import scatter.common.rest.validation.DictService;
import scatter.wwd.pojo.WwdConstants;
import scatter.wwd.pojo.form.ActivityAddForm;
import scatter.wwd.pojo.form.ActivityPageQueryForm;
import scatter.wwd.pojo.form.ActivityPageQueryForm1;
import scatter.wwd.pojo.form.ActivityUpdateForm;
import scatter.wwd.pojo.po.*;
import scatter.wwd.pojo.vo.ActivityDetailVo;
import scatter.wwd.pojo.vo.ActivityVo1;
import scatter.wwd.rest.WwdErrorCode;
import scatter.wwd.rest.mapper.ActivityMapper;
import scatter.wwd.rest.mapstruct.ActivityEnrollRuleMapStruct;
import scatter.wwd.rest.mapstruct.ActivityMapStruct;
import scatter.wwd.rest.mapstruct.ActivityParticipateMapStruct;
import scatter.wwd.rest.service.*;

import java.util.List;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

/**
 * <p>
 * 活动表 服务实现类
 * </p>
 *
 * @author yw
 * @since 2020-12-09
 */
@Slf4j
@Service
@Transactional
public class ActivityServiceImpl extends IBaseAddUpdateQueryFormServiceImpl<ActivityMapper, Activity, ActivityAddForm, ActivityUpdateForm, ActivityPageQueryForm> implements IActivityService {
    @Autowired
    @Setter
    private IActivityContentService iActivityContentService;

    @Autowired
    @Setter
    private IActivityEnrollRuleService iActivityEnrollRuleService;

    @Lazy
    @Autowired
    @Setter
    private IActivityParticipateService iActivityParticipateService;

    @Autowired
    @Setter
    private DictService dictService;
    @Autowired
    @Setter
    private IUserInfoService iUserInfoService;
    @Autowired
    @Setter
    private IAreaService iAreaService;

    @Qualifier("commonDbTaskExecutor")
    @Autowired
    @Setter
    private ExecutorService executorService;

    @Autowired
    @Setter
    private ICommentStarService iCommentStarService;
    @Autowired
    private ICommentRateService iCommentRateService;
    @Autowired
    private ICommentEnjoyService iCommentEnjoyService;

    @Autowired
    private ActivityMapper activityMapper;



    @Override
    public void preAdd(ActivityAddForm addForm, Activity po) {
        po.setCommentCount(0);
        po.setStarCount(0);
        po.setRateCount(0);
        // 默认添加一个活动得分为0
        po.setRateScore(0.0);
        po.setRateSum(0);
        po.setEnjoyCount(0);
        super.preAdd(addForm, po);

    }

    @Override
    public void preUpdate(ActivityUpdateForm updateForm, Activity po) {
        super.preUpdate(updateForm, po);

    }


    @Override
    public void postAdd(ActivityAddForm activityAddForm, Activity po) {
        ActivityContent content = new ActivityContent()
                .setContent(activityAddForm.getContent())
                .setActivityId(po.getId());
        iActivityContentService.save(content);
    }

    @Override
    public void postUpdate(ActivityUpdateForm activityUpdateForm, Activity po) {
        ActivityContent content = iActivityContentService.getByActivityId(po.getId());
        content = Optional.ofNullable(content).orElse(new ActivityContent());
        content.setActivityId(po.getId());
        content.setContent(activityUpdateForm.getContent());
        iActivityContentService.saveOrUpdate(content);
    }

    @Override
    protected void postDeleteById(String id, Activity po) {
        iActivityEnrollRuleService.remove(new QueryWrapper<ActivityEnrollRule>().lambda().eq(ActivityEnrollRule::getActivityId, po.getId()));
        iActivityContentService.remove(new QueryWrapper<ActivityContent>().lambda().eq(ActivityContent::getActivityId, po.getId()));
    }

    @Override
    public ActivityDetailVo getActivityDetailById(String id,String loginUserId) {

        int lastCount = 5;

        //        全部异步查询
        Future<Activity> activityFuture = executorService.submit(() -> getById(id));
        Future<ActivityEnrollRule> activityEnrollRuleFuture = executorService.submit(() -> iActivityEnrollRuleService.getByActivityId(id));
        Future<ActivityContent> activityContentFuture = executorService.submit(() -> iActivityContentService.getByActivityId(id));
        Future<IPage<ActivityParticipate>> participateFuture = executorService.submit(() -> iActivityParticipateService.listLatestParticipates(id, lastCount));

        Future<Boolean> hasStaredFuture = executorService.submit(() -> iCommentStarService.hasStared(id, loginUserId, WwdConstants.GROUP_FLAG_ACTIVITY_STAR));
        Future<Boolean> hasEnjoyedFuture = executorService.submit(() -> iCommentEnjoyService.hasEnjoyed(id, loginUserId, WwdConstants.GROUP_FLAG_ACTIVITY_ENJOY));
        Future<Boolean> hasRatedFuture = executorService.submit(() -> iCommentRateService.hasRated(id, loginUserId, WwdConstants.GROUP_FLAG_ACTIVITY_RATE));

        Future<Page<CommentStar>> commentStarPageFuture = executorService.submit(() -> iCommentStarService.listLatestStarForSubject(id, lastCount, WwdConstants.GROUP_FLAG_ACTIVITY_STAR));

        Future<Page<CommentEnjoy>> commentEnjoyPageFuture = executorService.submit(() -> iCommentEnjoyService.listLatestEnjoyForSubject(id, lastCount, WwdConstants.GROUP_FLAG_ACTIVITY_ENJOY));



        Activity activity = null;
        try {
            activity = activityFuture.get();
        } catch (InterruptedException e) {
            log.error("根据活动id获取活动被中断",e);
            throw new BusinessDataNotFoundException("数据不存在");
        } catch (ExecutionException e) {
            log.error("根据活动id获取活动异常",e);
            throw new BusinessDataNotFoundException("数据不存在");

        }

        if (!activity.getIsPublish()) {
            // 没有发布的数据直接请求，直接返回，如果能走到这里，可能数据在被抓取，否则是从后台进入的
            throw new BusinessDataNotFoundException("数据不存在，请通过正常渠道获取数据，小心你的行为");
        }

        ActivityDetailVo activityDetailVo = ActivityMapStruct.INSTANCE.poToActivityDetailVo(activity);
        ActivityEnrollRule activityEnrollRule = null;
        try {
            activityEnrollRule = activityEnrollRuleFuture.get();
        } catch (InterruptedException e) {
            log.error("根据活动id获取活动规则被中断",e);
            throw new BusinessDataNotFoundException("数据不存在");
        } catch (ExecutionException e) {
            log.error("根据活动id获取活动规则异常",e);
            throw new BusinessDataNotFoundException("数据不存在");
        }
        activityDetailVo.setEnrollRule(ActivityEnrollRuleMapStruct.INSTANCE.poToVo(activityEnrollRule));


        ActivityContent activityContent = null;
        try {
            activityContent = activityContentFuture.get();
        } catch (InterruptedException e) {
            log.error("根据活动id获取活动内容被中断",e);
            throw new BusinessDataNotFoundException("数据不存在");
        } catch (ExecutionException e) {
            log.error("根据活动id获取活动内容异常",e);
            throw new BusinessDataNotFoundException("数据不存在");
        }
        activityDetailVo.setActivityContent(activityContent.getContent());
        activityDetailVo.setIsParticipate(false);

        IPage<ActivityParticipate> byActivityIdAndIsQuit = null;
        try {
            byActivityIdAndIsQuit = participateFuture.get();
        } catch (InterruptedException e) {
            log.error("根据活动id获取活动参与信息被中断",e);
            throw new BusinessDataNotFoundException("数据不存在");
        } catch (ExecutionException e) {
            log.error("根据活动id获取活动参与信息异常",e);
            throw new BusinessDataNotFoundException("数据不存在");
        }
        if (!isStrEmpty(loginUserId) && !isEmpty(byActivityIdAndIsQuit.getRecords())) {
            long count = byActivityIdAndIsQuit.getRecords().stream().filter(i -> i.getUserId().equals(loginUserId)).count();
            if (count > 0) {
                activityDetailVo.setIsParticipate(true);
            }else {
                // 上面先遍历一下查出来最新的有没有，如果没有再去查库
                activityDetailVo.setIsParticipate(iActivityParticipateService.hasParticipated(id,loginUserId));
            }
        }
        activityDetailVo.setLatestParticipates(ActivityParticipateMapStruct.INSTANCE.pagePoToVo(byActivityIdAndIsQuit));

        // 点赞、想去最新数据
        try {
            activityDetailVo.setLatestCommentStars(CommentStarMapStruct.INSTANCE.pagePoToVo(commentStarPageFuture.get()));
            activityDetailVo.setLatestCommentEnjoys(CommentEnjoyMapStruct.INSTANCE.pagePoToVo(commentEnjoyPageFuture.get()));
        } catch (InterruptedException e) {
            log.error("根据活动id获取点赞、想去最新数据信息被中断",e);
        } catch (ExecutionException e) {
            log.error("根据活动id获取点赞、想去最新数据信息异常",e);
        }


        // 点赞、想去、评分
        try {
            Boolean hasStared = hasStaredFuture.get();
            Boolean hasEnjoyed = hasEnjoyedFuture.get();
            Boolean hasRated = hasRatedFuture.get();
            activityDetailVo.setIsHasStared(hasStared);
            activityDetailVo.setIsHasEnjoyed(hasEnjoyed);
            activityDetailVo.setIsHasRated(hasRated);
        } catch (InterruptedException e) {
            log.error("根据活动id获取点赞、想去、评分信息被中断",e);
        } catch (ExecutionException e) {
            log.error("根据活动id获取点赞、想去、评分信息异常",e);
        }

        return activityDetailVo;
    }
    
    @Override
    public IPage<ActivityVo1> getPage1(ActivityPageQueryForm1 pageQueryForm1,String currentUserId) {
        Page page = convertPage(pageQueryForm1);
        // 场地的字典id
        String idByGroupCodeWithValue = dictService.getIdByGroupCodeWithValue(pageQueryForm1.getPlaceTypeDictGroupCodeAndValue());
        LambdaQueryWrapper<Activity> queryWrapper = Wrappers.<Activity>lambdaQuery()
                .eq(Activity::getIsPublish, true)
                .eq(!isStrEmpty(idByGroupCodeWithValue), Activity::getPlaceTypeDictId, idByGroupCodeWithValue)
                .orderByDesc(Activity::getStartTime).orderByDesc(Activity::getCreateAt)
                ;
        if (pageQueryForm1.getIsSameCity() != null && pageQueryForm1.getIsSameCity()) {
            if(isStrEmpty(currentUserId)){
                throw new UserNotLoginException("需要登录");
            }else {
                UserInfo byUserId = iUserInfoService.getByUserId(currentUserId);
                if (isStrEmpty(byUserId.getNowAreaId())) {
                    // 如果没有完善信息，同城是看不了的，抛出异常，引导用户完善信息
                    throw new BusinessException("您的个人资料缺少当前所在城市信息哦，先去完善资料吧", WwdErrorCode.ERROR_NO_NOW_AREA.getCode());
                }
                Area byId = iAreaService.getById(byUserId.getNowAreaId());
                // 用户信息中存储的区id，其上一级是城市id
                queryWrapper.eq(Activity::getCityAreaId,byId.getParentId());
            }
        }
        Page page1 = page(page, queryWrapper);

        if (!isEmpty(page1.getRecords())) {
            List<ActivityVo1> activityVo1List = (List<ActivityVo1>) page1.getRecords().stream().map(item -> ActivityMapStruct.INSTANCE.poToActivityVo1(((Activity) item))).collect(Collectors.toList());
            page1.setRecords(activityVo1List);
        }

        return page1;
    }

    @Override
    public IPage<ActivityVo1> getPageForUser(BasePageQueryForm basePageQueryForm, String userId) {
        Assert.hasText(userId,"userId 不能为空");

        IPage activityIPage = activityMapper.userParticipateActivityPage(convertPage(basePageQueryForm), userId);
        if (!isEmpty(activityIPage.getRecords())) {
            List<ActivityVo1> activityVo1List = (List<ActivityVo1>) activityIPage.getRecords().stream().map(item -> ActivityMapStruct.INSTANCE.poToActivityVo1(((Activity) item))).collect(Collectors.toList());
            activityIPage.setRecords(activityVo1List);
        }
        return activityIPage;
    }
}
